<?php

namespace App\Http\Controllers\Api;

use App\Enums\AssetStatus;
use App\Enums\ProductStatus;
use App\Exceptions\ApiException;
use App\Http\Controllers\Controller;
use App\Models\Asset;
use App\Models\EntityApplyRecord;
use App\Models\FrontendUser;
use App\Models\Product;
use App\Models\RightsEntity;
use App\Models\RightsEntityProduct;
use App\Models\UserAddress;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Throwable;

class RightsEntityController extends Controller
{
    /**
     * @param $id
     *
     * @throws ApiException
     */
    public function getEntity($id): array
    {
        $entity = RightsEntity::query()->find($id);

        if (!$entity) {
            throw new ApiException('实物不存在.');
        }

        return Arr::only($entity->toArray(), [
            'name',
            'logo_url',
            'description',
        ]);
    }

    /**
     * @throws ApiException
     * @throws Throwable
     */
    public function exchanged()
    {
        $params = request()->validate([
            'entity_id' => 'required',
            'product_id' => 'required',
            'address_id' => 'required',
            'exchange_count' => 'required|integer|min:1',
        ]);

        /** @var FrontendUser $user */
        $user = Auth::user();

        if (!RightsEntityProduct::query()->where('product_id', $params['product_id'])->where(
            'entity_id',
            $params['entity_id']
        )->exists()) {
            throw new ApiException('实物和商品不存在关联关系.');
        }

        /** @var RightsEntity $entity */
        $entity = RightsEntity::query()->find($params['entity_id']);
        if (!$entity || $entity->status->is(ProductStatus::PAUSE)) {
            throw new ApiException('实物不存在或者已暂停发行.');
        }

        /** @var Product $product */
        $product = Product::query()->find($params['product_id']);

        $holdCount = Asset::query()
            ->where('user_id', $user->id)
            ->where('contract_address', $product->contract_address)
            ->where('asset_status', AssetStatus::HOLD)->count();

        if ($holdCount < $params['exchange_count']) {
            throw new ApiException('资产可兑换数量不足.');
        }

        /** @var UserAddress $address */
        $address = UserAddress::query()->where('user_id', $user->id)->find($params['address_id']);
        if (!$address) {
            throw new ApiException('收货地址不存在.');
        }

        DB::transaction(function () use ($user, $params, $entity, $product, $address) {
            /** @var EntityApplyRecord $record */
            $record = get_entity(EntityApplyRecord::class);
            $record->agent_id = $user->agent_id;
            $record->user_id = $user->id;
            $record->entity_id = $params['entity_id'];
            $record->product_id = $params['product_id'];
            $record->exchange_count = $params['exchange_count'];
            $record->address = $address->address;
            $record->save();
            $entity->exchange_count += $params['exchange_count'];
            $entity->save();

            Asset::query()
                ->where('user_id', $user->id)
                ->where('contract_address', $product->contract_address)
                ->where('asset_status', AssetStatus::HOLD)
                ->limit($params['exchange_count'])
                ->update(['asset_status' => AssetStatus::EXCHANGED, 'apply_id' => $record->id])
            ;
        });
    }

    /**
     * 兑换记录.
     */
    public function applyRecords(): array
    {
        $page = request()->page ?: 1;
        $limit = request()->limit ?: 10;

        /** @var FrontendUser $user */
        $user = Auth::user();

        $query = EntityApplyRecord::query()
            ->with(['user', 'entity'])
            ->where('user_id', $user->id)
            ->orderByDesc('id');
        $count = $query->count();
        $records = $query->offset(($page - 1) * $limit)->limit($limit)->get();

        $list = $records->map(function (EntityApplyRecord $record) {
            return [
                'id' => $record->id,
                'created_at' => $record->created_at->toDateTimeString(),
                'entity_name' => $record->entity->name,
                'entity_logo_url' => $record->entity->logo_url,
                'exchange_count' => $record->exchange_count,
                'logistics_no' => $record->logistics_no,
                'express_name' => $record->express_name,
                'status' => $record->status->value,
            ];
        });

        return [
            'list' => $list,
            'count' => $count,
        ];
    }
}
